package cn.bjxy.shishaolong.system.user.controller;


import cn.bjxy.shishaolong.common.ResultMsg;
import cn.bjxy.shishaolong.common.StatusCode;
import cn.bjxy.shishaolong.common.SysConst;
import cn.bjxy.shishaolong.system.entity.UserThirdAuthen;
import cn.bjxy.shishaolong.system.service.IUserThirdAuthenService;
import cn.bjxy.shishaolong.system.user.entity.SysUserInfo;
import cn.bjxy.shishaolong.system.user.entity.SysUserLocalAuthen;
import cn.bjxy.shishaolong.system.user.service.ISysUserInfoService;
import cn.bjxy.shishaolong.system.user.service.ISysUserLocalAuthenService;
import cn.bjxy.shishaolong.utils.SysUtil;
import cn.bjxy.shishaolong.utils.TokenUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.Data;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户本地认证 前端控制器
 * </p>
 *
 * @author 时少龙
 * @since 2019-03-25
 */
@RestController
@RequestMapping("/api/web/authen")
@CrossOrigin
@PropertySource("classpath:config/system-config.properties")
public class UserAuthenController {

    @Autowired
    private ISysUserLocalAuthenService authenService;
    @Autowired
    private TokenUtil tokenUtil;
    @Autowired
    private SysUtil sysUtil;

    @Setter
    @Value("${sys.admin.name}")
    private String systemAdminName;  // 将系统管理员的名字注入
    @Setter
    @Value("${sys.admin.no}")
    private String systemAdminNo;  // 将系统管理员的工号注入

    /**
     * 登录方法
     *
     * @param authen
     * @return
     */
    @PostMapping("/login")
    public ResultMsg login(@RequestBody SysUserLocalAuthen authen) {
        if (Objects.isNull(authen) || StringUtils.isEmpty(authen.getNo())
                || StringUtils.isEmpty(authen.getPassword())) {  // 健壮性判断
            return ResultMsg.create(StatusCode.PARAMETER_ERROR, StatusCode.PARAMETER_ERROR_MSG);
        }

        // 允许系统管理员使用admin 登录
        if (systemAdminName.equals(authen.getNo())) {
            authen.setNo(systemAdminNo);
        }

        // 使用用户名和密码查询
        String passWord = sysUtil.encodePassWord(authen);
        System.out.println(passWord);
        SysUserLocalAuthen resultLocalAuthen = authenService.getOne(new QueryWrapper<SysUserLocalAuthen>().lambda()
                .eq(SysUserLocalAuthen::getNo, authen.getNo())
                .eq(SysUserLocalAuthen::getPassword, sysUtil.encodePassWord(authen)));

        // 验证不通过
        if (Objects.isNull(resultLocalAuthen)) {
            return ResultMsg.create(StatusCode.USER_OR_PASSWORD_ERROR, StatusCode.USER_OR_PASSWORD_ERROR_MSG);
        }
        // 生成Token 返回给客户端
        String token = tokenUtil.createToken(resultLocalAuthen.getUserId());
        // 向客户端返回的信息集
        HashMap<String, Object> resultMap = new HashMap<>();
        resultMap.put(SysConst.RESULT_MAP_TOKEN, token);
        return ResultMsg.success(resultMap);
    }

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private IUserThirdAuthenService thirdAuthenService;
    @Autowired
    private ISysUserInfoService iSysUserInfoService;

    @Setter
    @Value("${auth.wx.appid}")
    private String appid;
    @Setter
    @Value("${auth.wx.secret}")
    private String secret;
    @Setter
    @Value("${auth.wx.grant_type}")
    private String grantType;

    private static String WX_AUTH_APPID = "appid";
    private static String WX_AUTH_SECRET = "secret";
    private static String WX_AUTH_GRANT_TYPE = "grant_type";

    /**
     * 微信登录方法
     *
     * @return
     */
    @PostMapping(value = "/wxLogin")
    public ResultMsg wxLogin(String code) {

        final String uri = "https://api.weixin.qq.com/sns/jscode2session";
        Map<String, String> param = new HashMap<>();
        param.put(WX_AUTH_APPID, appid);
        param.put(WX_AUTH_SECRET, secret);
        param.put(WX_AUTH_GRANT_TYPE, grantType);
        param.put("js_code", code);

        String result = restTemplate.getForObject(uri + convertParam(param), String.class);
        // 处理HTTP 请求 status

        System.out.println(result);
        if (!StringUtils.isEmpty(result)) {
            WxAuthResultMedel wxAuthResultMedel = JSONObject.parseObject(result, WxAuthResultMedel.class);
            System.out.println(wxAuthResultMedel);
            String errcode = wxAuthResultMedel.getErrcode();
            String openid = wxAuthResultMedel.getOpenid();
            String sessionKey = wxAuthResultMedel.getSession_key();
            // 成功
            if (!StringUtils.isEmpty(openid) && !StringUtils.isEmpty(sessionKey)) {
                // 判断
                UserThirdAuthen userThirdAuthenDb = thirdAuthenService.getOne(new QueryWrapper<UserThirdAuthen>().lambda().eq(UserThirdAuthen::getOpenid, wxAuthResultMedel.getOpenid()));
                SysUserInfo userInfo = null;
                Integer userId = null;
                if (userThirdAuthenDb == null) {
                    // 首次登录
                    // 保存用户信息
                    SysUserInfo sysUserInfo = new SysUserInfo()
                            .setName(wxAuthResultMedel.getOpenid()).setRoleId(4);
                    iSysUserInfoService.wxSave(sysUserInfo);
                    Integer userIdTemp = sysUserInfo.getTid();
                    // 保存 微信 openId
                    UserThirdAuthen userThirdAuthen = new UserThirdAuthen();
                    userThirdAuthen.setOuthType("wx")
                            .setUserId(userIdTemp)
                            .setOpenid(wxAuthResultMedel.getOpenid())
                            .setSessionKey(wxAuthResultMedel.getSession_key())
                            .setUnionid(wxAuthResultMedel.getUnionid());
                    thirdAuthenService.save(userThirdAuthen);
                    // TODO 获取access_token
                    userId = userIdTemp;
                } else {
                    // 二次登录
                    userId = userThirdAuthenDb.getUserId();
                    SysUserInfo userInfoTemp = iSysUserInfoService.getById(userId);
                    userInfo = wxAuthResultMedel.getOpenid().equals(userInfoTemp.getName()) ? null : userInfoTemp;
                }
                // 签发token
                String token = tokenUtil.createToken(userId);
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("token", token);
                resultMap.put("userInfo", userInfo);
                return ResultMsg.success(resultMap);
            } else {
                // TODO 错误情况 还需要单独处理
                return ResultMsg.create(Integer.parseInt(errcode), wxAuthResultMedel.getErrmsg());
            }
            // TODO 异常也需要做处理
        }
        return ResultMsg.create(-1, "获取未获取到信息！");
    }


    public static void main(String[] args) {
        Map<String, String> param = new HashMap<>();
        param.put(WX_AUTH_APPID, "fsd");
        param.put(WX_AUTH_SECRET, "sdfs");
        param.put(WX_AUTH_GRANT_TYPE, "sdfsd");
        param.put("js_code", "sdfsd");
        System.out.println(convertParam(param));
    }

    /**
     * 将map中村的参数 转成字符串
     *
     * @param paramMap
     * @return
     */
    private static String convertParam(Map<String, String> paramMap) {
        String paramStr = Optional.ofNullable(paramMap).orElse(new HashMap<>()).entrySet().stream()
                .map(entry -> entry.getKey() + "=" + entry.getValue()).collect(Collectors.joining("&"));
        return "?" + paramStr;
    }
}

@Data
@Accessors(chain = true)
class WxAuthResultMedel {
    private String openid;
    private String session_key;
    private String unionid;
    private String errcode;
    private String errmsg;
}
